package com.example.a2032.activity;

import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.example.a2032.R;
import com.example.a2032.Utils.BleSdk;
import com.example.a2032.Utils.DateUtils;
import com.example.a2032.Utils.EcgUtils;
import com.example.a2032.Utils.HistoryDataUploadUtils;
import com.example.a2032.Utils.ResolveUtil;
import com.example.a2032.Utils.SDUtil;
import com.example.a2032.Utils.SchedulersTransformer;
import com.example.a2032.Utils.SerialPortUtil;
import com.example.a2032.Utils.Utils;
import com.example.a2032.Utils.WebSocketUtils;
import com.example.a2032.entity.EcgMeasureResult;
import com.example.a2032.entity.EcgSaveInfo;
import com.example.a2032.net.jstylenet.JstyleConst;
import com.example.a2032.net.jstylenet.NetSendUtils;
import com.neurosky.AlgoSdk.NskAlgoDataType;
import com.neurosky.AlgoSdk.NskAlgoECGValueType;
import com.neurosky.AlgoSdk.NskAlgoSdk;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import lecho.lib.hellocharts.gesture.ContainerScrollType;
import lecho.lib.hellocharts.gesture.ZoomType;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.AxisValue;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.Viewport;
import lecho.lib.hellocharts.view.AbstractChartView;
import lecho.lib.hellocharts.view.LineChartView;

public class EcgMeasureActivity extends BaseActivity {


    @BindView(R.id.iv_back)
    ImageView ivBack;
    @BindView(R.id.iv_meausre_ready)
    ImageView ivMeausreReady;
    @BindView(R.id.tv_measure_tips1)
    TextView tvMeasureTips1;
    @BindView(R.id.tv_measure_tips2)
    TextView tvMeasureTips2;
    @BindView(R.id.LineChartView_ecg)
    LineChartView LineChartViewEcg;
    @BindView(R.id.tv_spoMeasureTime)
    TextView tvSpoMeasureTime;
    @BindView(R.id.iv_ecgHr)
    ImageView ivEcgHr;
    @BindView(R.id.tv_ecgMeasureHr)
    TextView tvEcgMeasureHr;
    @BindView(R.id.tv_ecgHrUnit)
    TextView tvEcgHrUnit;
    @BindView(R.id.ll_ecgResultTips)
    LinearLayout llEcgResultTips;
    @BindView(R.id.ll_measureTips)
    LinearLayout llMeasureTips;
    private NskAlgoSdk nskAlgoSdk;
    private int SignalQuality;

    int raw_data_index = 0;
    int maxEcgValue = 8000;
    private Disposable timerDisposable;
    private Disposable disposableMeasureTips;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        KeepScreenOn();
        setContentView(R.layout.activity_ecg_measure);
        ButterKnife.bind(this);
        init();
    }

    String from = "";

    private void init() {
        EcgUtils ecgUtils = new EcgUtils(this);
        nskAlgoSdk = ecgUtils.getNskAlgoSdk();
        nskAlgoSdk.setOnSignalQualityListener(new NskAlgoSdk.OnSignalQualityListener() {
            @Override
            public void onSignalQuality(int i) {
                SignalQuality = i;
                Log.i(TAG, "onSignalQuality: " + i);
            }

            @Override
            public void onOverallSignalQuality(int i) {

            }
        });
        nskAlgoSdk.setOnECGAlgoIndexListener(new NskAlgoSdk.OnECGAlgoIndexListener() {
            @Override
            public void onECGAlgoIndex(int type, final int value) {

                switch (type) {
                    case NskAlgoECGValueType.NSK_ALGO_ECG_VALUE_TYPE_SMOOTH:
                        //  Log.i(TAG, "onECGAlgoIndex: " + value);
                        int data = value;
                        fileEcgValue.add(value);
                        if (data > 8000) data = (int) (8000 - Math.random() * 500f);
                        if (data < -8000) data = (int) (-8000 + Math.random() * 500f);
                        drawEcgValue.add(data);
                        int size = drawEcgValue.size();
                        if (size >= maxSize) {
                            tmpEcgValue = new ArrayList<>(drawEcgValue);
                            uploadEcgData(tmpEcgValue, JstyleConst.Measure_Progress, currentHr);
                            drawEcgValue.clear();
                        }
                        if (size % 79 == 0) {
                            LineChartViewEcg.setLineChartData(getEcgLineChartData(Color.parseColor("#ff3939")));
                        }
                        break;
                    case NskAlgoECGValueType.NSK_ALGO_ECG_VALUE_TYPE_ROBUST_HR:
                        Log.i(TAG, "onECGAlgoIndex: hr " + value);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (SignalQuality < 3) return;
                            }
                        });

                        break;
                    case NskAlgoECGValueType.NSK_ALGO_ECG_VALUE_TYPE_HRV:
                        Log.i(TAG, "onECGAlgoIndex: hrv " + value);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (SignalQuality < 3) return;
//                                textViewEcgHrv.setText(String.valueOf(value));
//                                sendAction(hrvValueAction, String.valueOf(value));
                            }
                        });

                        break;
                }
            }
        });

        subscribe(this);
        sendData(BleSdk.enableEcgMeasure(true, true));
        initLineChart();
        showMeasureAnim();
        nskAlgoSdk.NskAlgoStart(false);
        from = getIntent().getStringExtra(KEY_MeasureFrom);
    }

    private void startDateTimer() {
        if (timerDisposable != null && !timerDisposable.isDisposed()) return;
        Log.i(TAG, "startDateTimer: ");
        Observable.intervalRange(1, 30, 0, 1, TimeUnit.SECONDS).compose(SchedulersTransformer.io2MainObservable()).subscribe(new Observer<Long>() {
            @Override
            public void onSubscribe(Disposable d) {
                timerDisposable = d;
            }

            @Override
            public void onNext(Long value) {
                tvSpoMeasureTime.setText(value + "");
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {
                Log.i(TAG, "onComplete: ");
                llEcgResultTips.setVisibility(View.VISIBLE);
                startFinishTimer();
                saveEcgFile();
                disableEcgMeasure();
            }
        });
    }

    Disposable disposableFinish;

    void startFinishTimer() {
        Utils.startMeasureTimer(5, TimeUnit.SECONDS, new Observer() {
            @Override
            public void onSubscribe(Disposable d) {
                disposableFinish = d;
            }

            @Override
            public void onNext(Object o) {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {
                finish();
            }
        });
    }

    void saveEcgFile() {
        if(hrv==-1)return;
        final List<Integer> temp = new ArrayList<>();
        temp.addAll(fileEcgValue);
        String time = DateUtils.getDefaultDate(new Date());
        String rootPath = SDUtil.getRootPath(this);
        EcgSaveInfo ecgSaveInfo = new EcgSaveInfo();
        ecgSaveInfo.setDate(time);
        ecgSaveInfo.setRootPath(rootPath);
        ecgSaveInfo.setHeartRate(currentHr);
        ecgSaveInfo.setMaxHeartRate(maxCurrentHr);
        ecgSaveInfo.setMinHeartRate(minCurrentHr);
        ecgSaveInfo.setHrv(hrv);
        Log.i(TAG, "saveEcgFile: " + maxCurrentHr + " " + minCurrentHr);
        if (TextUtils.isEmpty(from)) {
            //手动开启测量的时候，测量结束通过历史数据接口上传一次（定时传数据会有延迟）
            List data = new ArrayList();
            data.add(HistoryDataUploadUtils.getEcgData(ecgSaveInfo, temp));
            WebSocketUtils.getInstance().sendMsg(NetSendUtils.uploadHistoryData(JstyleConst.DataTYPE_ECG, data));
            SDUtil.saveEcgFile(ecgSaveInfo, temp);
        }

    }

    boolean isStart;

    private void showMeasureAnim() {

        Observable.timer(5, TimeUnit.SECONDS).compose(SchedulersTransformer.io2MainObservable()).subscribe(new Observer<Long>() {
            @Override
            public void onSubscribe(Disposable d) {
                disposableMeasureTips = d;
            }

            @Override
            public void onNext(Long aLong) {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {
                startDateTimer();
                llMeasureTips.setVisibility(View.GONE);
                isStart = true;
            }
        });
        //  Glide.with(this).asGif().load(R.mipmap.ecg_measure).into(ivMeasure);
    }

    int maxSize = 1536;

    void initLineChart() {
        initDataChartView(LineChartViewEcg, 0, 8000, maxSize, -8000);


    }

    List<Integer> tmpEcgValue = new ArrayList<>();
    List<Integer> drawEcgValue = new ArrayList<>();
    List<Integer> fileEcgValue = new ArrayList<>();

    public LineChartData getEcgLineChartData(int color) {
        LineChartData lineChartData = new LineChartData();
        List<Line> listLines = new ArrayList<>();
        List<AxisValue> axisValues = new ArrayList<>();
        Axis axisX = new Axis();
        axisX.setValues(axisValues);
        int size = drawEcgValue.size();
        Line drawLine = getEcgLine(color, drawEcgValue, 0);
        drawLine.setHasPoints(true);
        drawLine.setPointColor(Color.WHITE);
        listLines.add(drawLine);
        if (tmpEcgValue.size() != 0) {
            Line tmpLine = getEcgLine(color, tmpEcgValue, size + 300);
            listLines.add(tmpLine);
        }
        lineChartData.setLines(listLines);
        lineChartData.setAxisXBottom(axisX.setHasAxisLines(false));
        return lineChartData;
    }

    Line getEcgLine(int color, List<Integer> list, int start) {
        Line line = new Line();
        List<PointValue> listPoint = new ArrayList<>();
        for (int i = start; i < list.size(); i++) {
            PointValue pointValue = new PointValue();
            float data = list.get(i);

            pointValue.set(i, data);
            listPoint.add(pointValue);
        }
        line.setValues(listPoint);
        line.setColor(color);
        line.setCubic(true);
        line.setStrokeWidth(2);
        line.setHasPoints(false);
        return line;
    }

    public void initDataChartView(AbstractChartView chart, float left, float top, float right, float bottom) {
        Viewport viewport = chart.getCurrentViewport();
        viewport.top = top;
        viewport.bottom = bottom;
        viewport.left = left;
        viewport.right = right;
        chart.setScrollEnabled(true);
        chart.setContainerScrollEnabled(true, ContainerScrollType.VERTICAL);
        chart.setViewportCalculationEnabled(false);
        chart.setMaximumViewport(viewport);
        chart.setZoomType(ZoomType.HORIZONTAL_AND_VERTICAL);
        chart.setCurrentViewport(viewport, false);
    }


    int currentHr = 0;
    int maxCurrentHr = 0;
    int minCurrentHr = 255;
    int hrv = -1;

    @Override
    public void EcgMeasureData(EcgMeasureResult ecgMeasureResult) {
        super.EcgMeasureData(ecgMeasureResult);
        if (isDestroyed() || !isStart) return;
        byte[] value = ecgMeasureResult.getEcgValue();
        int status = ecgMeasureResult.getSignalQuality();
        if (status == 0) {
            llMeasureTips.setVisibility(View.VISIBLE);
            unSubscribe(timerDisposable);
            uploadEcgData(new ArrayList<>(), 5, currentHr);
            fileEcgValue.clear();
        } else {
            startDateTimer();
            llMeasureTips.setVisibility(View.GONE);
            int heartValue = ecgMeasureResult.getHrValue();
            currentHr = heartValue;
            hrv = ecgMeasureResult.getHrvValue();
            Log.i(TAG, "EcgMeasureData: " + hrv);
            if (heartValue != 0) {
                maxCurrentHr = Math.max(maxCurrentHr, heartValue);
                minCurrentHr = Math.min(minCurrentHr, heartValue);
            }

            tvEcgMeasureHr.setText(Utils.getShowMeasureValue(heartValue));
            if (raw_data_index == 0 || raw_data_index % 200 == 0) {
                // send the good signal for every half second
                short pqValue[] = {(short) 200};
                nskAlgoSdk.NskAlgoDataStream(NskAlgoDataType.NSK_ALGO_DATA_TYPE_ECG_PQ, pqValue, 1);
            }
            for (int i = 0; i < value.length / 2 - 1; i++) {
                int ecgValueAction = ResolveUtil.getValue(value[i * 2], 1) + ResolveUtil.getValue(value[i * 2 + 1], 0);
                if (ecgValueAction >= 32768) ecgValueAction = ecgValueAction - 65536;
                raw_data_index++;
                short[] ecgData = new short[]{(short) -ecgValueAction};
                nskAlgoSdk.NskAlgoDataStream(NskAlgoDataType.NSK_ALGO_DATA_TYPE_ECG, ecgData, 1);
            }
        }


    }


    private static final String TAG = "EcgMeasureActivity";


    boolean isMeasure = true;

    @Override
    protected void onDestroy() {
        super.onDestroy();
        disableEcgMeasure();
        unSubscribe(disposableMeasureTips);
        unSubscribe(timerDisposable);
        unSubscribe(disposableFinish);
    }

    void disableEcgMeasure() {
        if (!isMeasure) return;
        SerialPortUtil.getInstance().restartEcgSerialPort();
        WebSocketUtils.getInstance().setMeasuring(false);
        uploadEcgData(new ArrayList<>(), JstyleConst.Measure_Finish, currentHr);
        isMeasure = false;
    }


    @Override
    protected void stopMeasure() {
        super.stopMeasure();
        finish();
    }

    private void uploadEcgData(List<Integer> ecgData, int state, int heartRate) {
        if (TextUtils.isEmpty(from)) return;
        String msg = NetSendUtils.realTimeEcgData(ecgData, state, heartRate, hrv, from);
        WebSocketUtils.getInstance().sendMsg(msg);

    }
}